package tp.fil.main;

import java.io.IOException;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

public class MetricsComputation {
	
	public static void main(String[] args) {
		try {
			Resource javaMetamodel;
			Resource javaModel;
			Resource metricsModel;
			Resource metricsMetamodel;
			
			//Create and configure resource set
			ResourceSet resSet = new ResourceSetImpl();
			resSet.getResourceFactoryRegistry().
				getExtensionToFactoryMap().
				put("ecore", new EcoreResourceFactoryImpl());
			XMIResourceFactoryImpl xmiFactory = new XMIResourceFactoryImpl();
			resSet.getResourceFactoryRegistry().
				getExtensionToFactoryMap().
				put("xmi", xmiFactory);
			
			//Load Java & Metrics metamodel
			javaMetamodel = resSet.createResource(URI.createFileURI("src/tp/fil/resources/Java.ecore"));
			javaMetamodel.load(null);
			EPackage.Registry.INSTANCE.put("http://www.eclipse.org/MoDisco/Java/0.2.incubation/java", 
					javaMetamodel.getContents().get(0));
			
			metricsMetamodel = resSet.createResource(URI.createFileURI("src/tp/fil/resources/Metrics.ecore"));
			metricsMetamodel.load(null);
			EPackage.Registry.INSTANCE.put("http://metrics", 
					metricsMetamodel.getContents().get(0));
			
			//Load Java model
			javaModel = resSet.createResource(URI.createFileURI("../PetStore/PetStore_java.xmi"));
			javaModel.load(null);
			
			//Initiate Metrics model
			metricsModel = resSet.createResource(URI.createFileURI("../PetStore/PetStore_metrics.xmi"));
			
			/*
			 * TO BE COMPLETED...
			 */
			EPackage metricsPackage = (EPackage) metricsMetamodel.getContents().get(0);
			EClass metricsNumbersWrapperClass = (EClass) metricsPackage.getEClassifier("Numbers");
			EClass metricsClassWrapperClass = (EClass) metricsPackage.getEClassifier("MetricsClass");
			EClass metricsMethodWrapperClass = (EClass) metricsPackage.getEClassifier("MetricsMethod");
			
			TreeIterator<EObject> treeIterator = javaModel.getAllContents();
			EObject eObject = null;
			
			// counter and container
			EList<EObject> eListMethods = new BasicEList<EObject>();
			EList<EObject> eListClass = new BasicEList<EObject>();
			int numberOfClass = 0;
			int numberOfMethod = 0;
			int numberOfInterface = 0;
			int numberOfLine = 0;
			
			while(treeIterator.hasNext()){
				eObject = treeIterator.next();
				if(eObject.eClass().getName().equals("ClassDeclaration")){
					numberOfClass++;
										
					// counter
					int numberOfMethodsInClass = 0;
					int numberOfVariablesInClass = 0;
					
					// class data
					for(EObject eClassObject : eObject.eContents()){
						
						if(eClassObject.eClass().getName().equals("MethodDeclaration")){
							numberOfMethodsInClass++;
						}
						if(eClassObject.eClass().getName().equals("FieldDeclaration")){
							numberOfVariablesInClass++;
						}
					}
					
					EObject metricsClassWrapperObject = metricsPackage.getEFactoryInstance().create(metricsClassWrapperClass);
					metricsClassWrapperObject.eSet(metricsClassWrapperClass.getEStructuralFeature("numberOfMethods"), numberOfMethodsInClass);
					metricsClassWrapperObject.eSet(metricsClassWrapperClass.getEStructuralFeature("numberOfVariables"), numberOfVariablesInClass);
					eListClass.add(metricsClassWrapperObject);
					
					
				}else if(eObject.eClass().getName().equals("MethodDeclaration")){
					
					// counter
					int numberOfAttribute = 0;
					int numberOfStatement = 0;
					int numberOfVariables = 0;
					
					// method data
					for(EObject eMethodObject : eObject.eContents()){
						if(eMethodObject.eClass().getName().equals("SingleVariableDeclaration")){
							numberOfAttribute++;
						}
						if(eMethodObject.eClass().getName().equals("Block")){
							for(EObject eBlock : eMethodObject.eContents()){
								if (eBlock.eClass().getName().equals("VariableDeclarationStatement"))
								numberOfVariables++;
							}
							numberOfStatement = eMethodObject.eContents().size();
							numberOfLine += numberOfStatement;
						}
					}
					
					EObject metricsMethodWrapperObject = metricsPackage.getEFactoryInstance().create(metricsMethodWrapperClass);
					metricsMethodWrapperObject.eSet(metricsMethodWrapperClass.getEStructuralFeature("numberOfAttributes"), numberOfAttribute);
					metricsMethodWrapperObject.eSet(metricsMethodWrapperClass.getEStructuralFeature("numberOfLines"), numberOfStatement);
					metricsMethodWrapperObject.eSet(metricsMethodWrapperClass.getEStructuralFeature("numberOfVariables"), numberOfVariables);
					eListMethods.add(metricsMethodWrapperObject);
					
					// number method 
					numberOfMethod++;
					
				}else if(eObject.eClass().getName().equals("InterfaceDeclaration")){
					numberOfInterface++;
				}
			}
			
		
			//Serialize Metrics model
			EObject metricsWrapperObject = metricsPackage.getEFactoryInstance().create(metricsNumbersWrapperClass);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("numberOfClass"), numberOfClass);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("numberOfMethod"), numberOfMethod);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("averageMethodPerClass"), (Integer)numberOfMethod / numberOfClass);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("numberOfInterface"), numberOfInterface);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("numberOfLines"), numberOfLine);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("listMethods"), eListMethods);
			metricsWrapperObject.eSet(metricsNumbersWrapperClass.getEStructuralFeature("listClass"), eListClass);
					
			metricsModel.getContents().add(metricsWrapperObject);
			metricsModel.save(null);
			
			//Unload models and metamodels
			javaModel.unload();
			metricsModel.unload();
			EPackage.Registry.INSTANCE.remove("http://www.eclipse.org/MoDisco/Java/0.2.incubation/java");
			javaMetamodel.unload();
			EPackage.Registry.INSTANCE.remove("http://metrics");
			metricsMetamodel.unload();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
